import {
  ATTR,
  TEXT,
  REMOVE,
  REPLACE
} from './patchTypes';
import {
  setAttrs,
  render
} from './virtualDom';

import Element from './Element';

let finalPatches = {},
  //realNodeIndex
  rnIndex = 0;

function doPatch(rDom, patches) {
  finalPatches = patches;
  rNodeWalk(rDom);

}

function rNodeWalk(rNode) {
  //每取一次 加1
  const rnPatch = finalPatches[rnIndex++],
    childNodes = rNode.childNodes;

  //类数组转数组
  [...childNodes].map((c) => {
    //遍历子节点并再次递归
    rNodeWalk(c);
  });

  //有不存在的情况
  if (rnPatch) {
    //存在时打补丁
    patchAction(rNode, rnPatch);
  }

}

/**
 * 打补丁
 * @param {*} rNode 真实节点
 * @param {*} rnPatch 真实节点的补丁
 */
function patchAction(rNode, rnPatch) {
  //遍历每个数组底下嵌套的多个补丁包
  rnPatch.map((p) => {
    switch (p.type) {
      case ATTR:
        //拿到每个补丁对象下的attrs
        for (let key in p.attrs) {
          const value = p.attrs[key];

          if (value) {
            setAttrs(rNode, key, value);
          } else {
            //undefined时，不存在
            //删除key
            rNode.removeAttribute(key);
          }
        }
        break;
      case TEXT:
        rNode.textContent = p.text;
        break;
      case REPLACE:
        //如果是Element构造出来说明是虚拟node
        const newNode = (p.newNode instanceof Element) ?
          //再渲染一次
          render(p.newNode) :
          //文本节点
          document.createTextNode(p.newNode);

        //把原来的node替换为新的node
        rNode.parentNode.replaceChild(newNode, rNode);
        break;
      case REMOVE:
        //删除自己的节点
        rNode.parentNode.removeChild(rNode);
        break;
      default:
        break;
    }
  });
}

export default doPatch;